package com.pangu.message.constant;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.JSONSerializable;
import com.alibaba.fastjson.serializer.JSONSerializer;
import com.pangu.message.Message;
import com.pangu.message.PanguMessage;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.val;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;

import static java.util.Optional.empty;

/**
 * @author Linbizhao
 * @description: 消息小类
 * @since 2023/11/23 15:40
 */
@Getter
@AllArgsConstructor
public enum MessageType implements JSONSerializable {

    UNKNOWN("unknown", MessageCategory.UNKNOWN, PanguMessage::new),
    ;

    /**
     * 消息小类名称
     */
    private final String value;

    /**
     * 所归属大类
     */
    private final MessageCategory category;

    /**
     * 实例化
     */
    private final Supplier<? extends Message> messageInstance;

    /**
     * Convert message optional
     *
     * @param map inData
     * @param <T> the type parameter
     */
    public static <T extends Message> Optional<T> convertMessage(Map<String, Object> map) {
        return of(map)
                .map(type -> type.convert(map));
    }

    /**
     * Of optional.
     *
     * @param map the map
     * @return the optional
     */
    public static Optional<MessageType> of(Map<String, Object> map) {
        val json = new JSONObject(map);
        val c = json.getString("category");
        val t = json.getString("type");

        for (MessageType mt : MessageType.values()) {
            if (mt.getCategory().getValue().equals(c)
                    && mt.getValue().equals(t)) {
                return Optional.of(mt);
            }
        }
        return empty();
    }


    @Override
    public void write(JSONSerializer serializer, Object fieldName, Type fieldType, int features) throws IOException {

    }

    /**
     * singleton instance convert
     */
    @SuppressWarnings("all")
    public <T extends Message> T convert(Map<String, Object> map) {
        if (messageInstance != null) {
            val json = new JSONObject(map);
            return (T) json.toJavaObject(messageInstance.get().getClass());
        }
        return null;
    }
}
